#ifndef DSPSIMULATOR_BITTOOLS_H
#define DSPSIMULATOR_BITTOOLS_H

#include <bitset>
#include <vector>
#include <sstream>
#include <iomanip>
#include <simulatorV1/type/type.h>

/**
 * 检查src以第begin个bit开始的bit串是否等于target
 * @param src 源bit串
 * @param begin bit比较的起始下标
 * @param target 目标bit串
 * @return 如果在源bit串中，以第begin个bit开始的bit串等于目标bit串，返回true，否则返回false
 */
template<u32 size>
bool checkBits(const std::bitset<32> &src, u32 begin, const std::bitset<size> &target) {
    if (size > 32)
        return false;

    for (u32 i = 0; i < size; i++) {
        if (src[i + begin] != target[i])
            return false;
    }
    return true;
}

template<u32 size>
bool checkBits(const std::bitset<16> &src, u32 begin, const std::bitset<size> &target) {
    if (size > 16)
        return false;

    for (u32 i = 0; i < size; i++) {
        if (src[i + begin] != target[i])
            return false;
    }
    return true;
}

/**
 * 从32位数据中获取指定数量的bit数据
 * @tparam size  需要获取的bit数据大小
 * @param src   32位bit数据
 * @param begin 需要获取的bit是起始地址
 * @return 获取的size位bit
 */
template<u32 size>
std::bitset<size> extractBits(const std::bitset<32> &src, u32 begin) {
    if (begin >= 32 || size == 0)
        return {};

    if (begin + size < begin)
        return {};

    if (begin + size > 32)
        return {};

    std::bitset<size> res;
    for (u32 i = 0; i < size; i++)
        res[i] = src[begin + i];
    return std::move(res);
}

template<u32 size>
std::bitset<size> extractBits(const std::bitset<16> &src, u32 begin) {
    if (begin >= 16 || size == 0)
        return {};

    if (begin + size < begin)
        return {};

    if (begin + size > 16)
        return {};

    std::bitset<size> res;
    for (u32 i = 0; i < size; i++)
        res[i] = src[begin + i];
    return res;
}

/**
 * 从输入数据的0位bit开始读取指定数量的bit，并将读取的bit转为int变量
 * @tparam size 需要读取的bit数
 * @param num 输入数据
 * @return 读取的bit转为的int变量
 */
template<u32 size>
i32 extractBitsAndToInt(u32 num) {
    if (size == 0)
        return 0;

    std::bitset<size> data(num);
    u32 i = 0;
    i32 res = 0;
    for (; i < data.size() - 1; i++) {
        if (data[i] == 1)
            res += 1 << i;
    }
    if (data[i] == 1)
        res -= 1 << i;
    return res;
}

/**
* 从输入数据的0位bit开始读取指定数量的bit，并将读取的bit转为int变量
* @tparam size 需要读取的bit数
* @param data 输入数据
* @return 读取的bit转为的int变量
*/
template<u32 size>
i32 extractBitsAndToInt(const std::bitset<size> &data) {
    if (size == 0)
        return {};
    u32 i = 0;
    i32 res = 0;
    for (; i < data.size() - 1; i++) {
        if (data[i] == 1)
            res += 1 << i;
    }
    if (data[i] == 1)
        res -= 1 << i;
    return res;
}

/**
 * //将int/uint转成16进制字符串
 * @param i 输入的int/uint变量
 * @return 16进制字符串
 */
template<typename T>
std::string dec2hex(T i) {
    if (i == 0) {
        return {"0X00"};
    }
    std::stringstream ioss; //定义字符串流
    std::string s_temp; //存放转化后字符
    ioss << std::setiosflags(std::ios::uppercase) << std::hex << i; //以十六制(大写)形式输出
    ioss >> s_temp;
    s_temp = "0X" + s_temp;
    return s_temp;
}

/**
 * 将vector<u8>类型的数据转换为bitset类型
 * @tparam size bit类型大小
 * @param data
 * @return
 */
template<u32 size>
std::bitset<size> vectorToBitSet(const std::vector<u8> &data) {
    if (data.empty())
        return {0};
    u32 res = 0;
    for (u32 i = 0; i < data.size(); i++) {
        res += data[i] << (i << 3);
    }
    return {res};
}

#endif //DSPSIMULATOR_BITTOOLS_H
